/*
 * Copyright (c) 2017, www.zm0618.com All Rights Reserved..
 */

package com.light.hessian.provider.discovery;

import com.light.hessian.remoting.client.balance.Balance;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.ClassUtils;

import java.io.IOException;
import java.util.Properties;

/**
 * Created by zhaojun on 2017/02/09.
 */
public abstract class AbstractProviderDiscoverer implements InitializingBean,BeanNameAware {


    protected static  final Logger logger= LoggerFactory.getLogger(AbstractProviderDiscoverer.class);

    private boolean autoDiscovery;
    private String provider;
    private DiscoveryType discoveryType;
    private String registryConf;
    private String protocol="http";//与注册中心交互协议
    private Balance balance;
    private String beanName;

    protected static Properties registryConfProperties;

    @Override
    public void setBeanName(String beanName) {
        this.beanName=beanName;
    }


    protected void prepare(){
        loadRegistryConf();
        handleRegistryConf();
    }

    protected void handleRegistryConf(){
        discoveryType=determineDiscoverType();
        balance=determineBalance();
        ProviderRegistryConfParser  registryConfParser=null;
        if (DiscoveryType.local==discoveryType){//本地
            registryConfParser=new ProviderRegistryLocalConfigParser();
        }
        if (DiscoveryType.consul==discoveryType){//注册到consul
            registryConfParser= new ProviderRegistryConsulConfParser();
        }
        if (registryConfParser!=null){
            registryConfParser.doParse(this);
        }
    }

    private Balance determineBalance() {
        String balanceValue=getRegistryConfProperties().getProperty(String.format("%s.provider.client.balance",getProvider()));
        if (StringUtils.isNotBlank(balanceValue)){
            return Balance.valueOf(balanceValue);
        }
        return this.balance;
    }

    private DiscoveryType determineDiscoverType() {
        String discoveryTypeValue = getRegistryConfProperties().getProperty(String.format("%s.provider.discovery.type", getProvider()));
        if (StringUtils.isNotBlank(discoveryTypeValue)){
            return DiscoveryType.valueOf(discoveryTypeValue);
        }
        return this.discoveryType;
    }

    protected abstract void handleDiscoveryReference(DiscoverBaseReference discoverReference) ;


    private void loadRegistryConf() {
        try {
            if (registryConfProperties==null){
                synchronized (AbstractProviderDiscoverer.class){
                    if (registryConfProperties==null){
                        ClassPathResource registryConfResource=new ClassPathResource(registryConf,ClassUtils.getDefaultClassLoader());
                        registryConfProperties = PropertiesLoaderUtils.loadProperties(registryConfResource);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Properties getRegistryConfProperties() {
        return registryConfProperties;
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        logger.debug("#{} discovery type ==>{}",this.discoveryType,this.provider);
        prepare();
    }

    public String getProvider() {
        return provider;
    }

    public void setProvider(String provider) {
        this.provider = provider;
    }

    public boolean isAutoDiscovery() {
        return autoDiscovery;
    }

    public void setAutoDiscovery(boolean autoDiscovery) {
        this.autoDiscovery = autoDiscovery;
    }

    public DiscoveryType getDiscoveryType() {
        return discoveryType;
    }

    public void setDiscoveryType(DiscoveryType discoveryType) {
        this.discoveryType = discoveryType;
    }

    public String getRegistryConf() {
        return registryConf;
    }

    public void setRegistryConf(String registryConf) {
        this.registryConf = registryConf;
    }

    public String getProtocol() {
        return protocol;
    }

    public void setProtocol(String protocol) {
        this.protocol = protocol;
    }

    public Balance getBalance() {
        return balance;
    }

    public void setBalance(Balance balance) {
        this.balance = balance;
    }
}
